bitkeeper revision 1.206 (3eb7820fjxOimwW6NMSeo6KyAdqZUQ)
authortlh20@elite.cl.cam.ac.uk <tlh20@elite.cl.cam.ac.uk>
Tue, 6 May 2003 09:36:15 +0000 (09:36 +0000)
committertlh20@elite.cl.cam.ac.uk <tlh20@elite.cl.cam.ac.uk>
Tue, 6 May 2003 09:36:15 +0000 (09:36 +0000)
Many files:
  new file
  domctl, xi_ tools, updated domain builder, /proc/xeno/domains

38 files changed:
.bk-to-hg
.hg-to-bk
.rootkeys
BitKeeper/etc/logging_ok
tools/domain_builder/dom_builder.c
tools/domain_builder/dom_kill.c
tools/domctl/Makefile [new file with mode: 0644]
tools/domctl/build.xml [new file with mode: 0644]
tools/domctl/domctl [new file with mode: 0755]
tools/domctl/domctl.xml [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Command.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandDestroy.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandHelp.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandNew.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStart.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStop.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Defaults.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Main.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Settings.java [new file with mode: 0644]
tools/domctl/src/uk/ac/cam/cl/xeno/domctl/StringPattern.java [new file with mode: 0644]
tools/internal/Makefile [new file with mode: 0644]
tools/internal/dom0_defs.h [new file with mode: 0644]
tools/internal/hypervisor_defs.h [new file with mode: 0644]
tools/internal/mem_defs.h [new file with mode: 0644]
tools/internal/xi_build.c [new file with mode: 0644]
tools/internal/xi_create.c [new file with mode: 0644]
tools/internal/xi_destroy.c [new file with mode: 0644]
tools/internal/xi_start.c [new file with mode: 0644]
tools/internal/xi_stop.c [new file with mode: 0644]
tools/internal/xi_vifinit [new file with mode: 0755]
xen/common/dom0_ops.c
xen/common/domain.c
xen/common/schedule.c
xen/include/xeno/dom0_ops.h
xen/include/xeno/sched.h
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_core.c
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_ops.h

index 1d83a2cea7a1381f7f984f71aaa8137d0f9259e7..ee55de0843e98340915a04fe4708d2c6805415c2 100755 (executable)
--- a/.bk-to-hg
+++ b/.bk-to-hg
@@ -2,5 +2,7 @@
 set -e
 test -L tools/domain_builder/dom0_ops.h
 rm      tools/domain_builder/dom0_ops.h
+test -L tools/internal/dom0_ops.h
+rm      tools/internal/dom0_ops.h
 (find -depth -type d -print | xargs -r rmdir 2>/dev/null) || true
 exit 0
index 9c6992a3202885d7d4747b5ae5eaec5d3d01e04d..2bde70313914790158b1e405dc8f29a83ce41a76 100755 (executable)
--- a/.hg-to-bk
+++ b/.hg-to-bk
@@ -3,5 +3,7 @@ set -e
 mkdir -p tools
 mkdir -p tools/domain_builder
 ln -s ../../xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_ops.h tools/domain_builder/dom0_ops.h
+mkdir -p tools/internal
+ln -s ../../xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_ops.h tools/internal/dom0_ops.h
 (find -depth -type d -print | xargs -r rmdir 2>/dev/null) || true
 exit 0
index efe0d08fe2f462c8087f4a0c0401060b48765b31..92bdbddc820a92a880b6a7b0a5774144fa0f07db 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3e71afadoAI0VvAGKebLpToVQxUKfQ tools/domain_builder/mynewdom
 3e4d0046VHhXwFuG5FK34AVxqd5A_A tools/domain_builder/newdom
 3e4d0046IBzDIeaMbQB-e2QB2ahbig tools/domain_builder/vifinit
+3eb781edFwm_pW9FwnQACIe68viLOw tools/domctl/Makefile
+3eb781fcTp_LPQwaot3SSSehkaf4eg tools/domctl/build.xml
+3eb781fcXf-WczEdAhnTpWfbR55jqA tools/domctl/domctl
+3eb781fcabCKRogwxJA3-jJKstw9Vg tools/domctl/domctl.xml
+3eb781fcffCXkrcWLBxUTOfQFa3Saw tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Command.java
+3eb781fcOLcVAcqnZOAikur6sAP0rA tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandDestroy.java
+3eb781fcQuQVSKxKtp4fBgPOwx7DDw tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandHelp.java
+3eb781fcRYdxK1HbjBX7r7VlO5PS0w tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandNew.java
+3eb781fcbp9IAHTl40CoMavY1FNd_g tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStart.java
+3eb781fdRXSsyEre7LxCmPJMpB5BaQ tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStop.java
+3eb781fdX_thm9iHSxQ8vqQ0fL7Ncg tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Defaults.java
+3eb781fdTWJr8RPdfuG20IC0CzYL2A tools/domctl/src/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.java
+3eb781fdA8LFQEYE2fXg1JDB9OceYA tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Main.java
+3eb781fd_CgRvlaIBkJjxUSnuvCuHQ tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Settings.java
+3eb781fdFDS4lap1-3ZVDtbKZfpVZA tools/domctl/src/uk/ac/cam/cl/xeno/domctl/StringPattern.java
+3eb781fdl4lXWYZzmqDDUAYhAThRqQ tools/internal/Makefile
+3eb781fdc539MQQm47rYRCCR3N5i-Q tools/internal/dom0_defs.h
+3eb781fdEYILyFg60YVBsWNqxWFf1g tools/internal/dom0_ops.h
+3eb781fddjylXbsepjppUyIXa5lcaQ tools/internal/hypervisor_defs.h
+3eb781fdKiQbgozBsgs_zzJQ9ubehw tools/internal/mem_defs.h
+3eb781fdgbSkh2O6JQS-65Dz4n0ItQ tools/internal/xi_build.c
+3eb781fdW1SAyiaC4mTsXq_9fRHh-A tools/internal/xi_create.c
+3eb781fdcJ0fF7rWfzAOArW-x4-gwA tools/internal/xi_destroy.c
+3eb781fd8oRfPgH7qTh7xvgmwD6NgA tools/internal/xi_start.c
+3eb781fd0Eo9K1jEFCSAVzO51i_ngg tools/internal/xi_stop.c
+3eb781fd7211MZsLxJSiuy7W4KnJXg tools/internal/xi_vifinit
 3ea53c6dz47kAOwpk54f8_zOAQ5ngw tools/vdmanager/build.xml
 3eaff785PwN0C3-xhCf_zMCL27JIgQ tools/vdmanager/notes.xml
 3ea53c6dE-azH1i1VJmJMp9SHnETkQ tools/vdmanager/src/uk/ac/cam/cl/xeno/vdmanager/Extent.java
index 9ec62d9ca9b4ffb1c886fd43a00ba4ecefbeb38b..9cc9e724e8d6ddb785da2c95d66c6239ee914889 100644 (file)
@@ -18,3 +18,4 @@ rn@wyvis.camb.intel-research.net
 rn@wyvis.research.intel-research.net
 smh22@boulderdash.cl.cam.ac.uk
 smh22@uridium.cl.cam.ac.uk
+tlh20@elite.cl.cam.ac.uk
index 13ee8d8735cad3556e928763accbe5444d3c507a..d1cc68d704c4e58ab78b2c11e5e742c888331f40 100644 (file)
@@ -49,7 +49,7 @@ static int do_kill_domain(int dom_id, int force)
     dom0_op_t dop;
     int cmd_fd;
 
-    dop.cmd = DOM0_KILLDOMAIN;
+    dop.cmd = DOM0_DESTROYDOMAIN;
     dop.u.killdomain.domain = dom_id;
     dop.u.killdomain.force  = force;
 
@@ -178,8 +178,9 @@ static dom0_newdomain_t * create_new_domain(long req_mem)
         return 0;
     }
 
-    dop.cmd = DOM0_NEWDOMAIN;
+    dop.cmd = DOM0_CREATEDOMAIN;
     dop.u.newdomain.memory_kb = req_mem;
+    dop.u.newdomain.name[0] = 0;
 
     write(cmd_fd, &dop, sizeof(dom0_op_t));
     close(cmd_fd);
@@ -435,7 +436,11 @@ static int launch_domain(dom_meminfo_t  * meminfo)
         return -1;
     }
 
-    dop.cmd = DOM0_STARTDOM;
+    dop.cmd = DOM0_BUILDDOMAIN;
+    memcpy(&dop.u.meminfo, meminfo, sizeof(dom_meminfo_t));
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+
+    dop.cmd = DOM0_STARTDOMAIN;
     memcpy(&dop.u.meminfo, meminfo, sizeof(dom_meminfo_t));
     write(cmd_fd, &dop, sizeof(dom0_op_t));
 
index ddc0f8a4fdbfc52ca5642bbd96326ef888a5deb2..b27fca9a5871421f35f22915ebc3572432efca2d 100644 (file)
@@ -21,7 +21,7 @@ static int do_kill_domain(int dom_id, int force)
     dom0_op_t dop;
     int cmd_fd;
 
-    dop.cmd = DOM0_KILLDOMAIN;
+    dop.cmd = DOM0_DESTROYDOMAIN;
     dop.u.killdomain.domain = dom_id;
     dop.u.killdomain.force  = force;
 
diff --git a/tools/domctl/Makefile b/tools/domctl/Makefile
new file mode 100644 (file)
index 0000000..054fb95
--- /dev/null
@@ -0,0 +1,5 @@
+default:
+       ant dist
+
+clean:
+       ant clean
diff --git a/tools/domctl/build.xml b/tools/domctl/build.xml
new file mode 100644 (file)
index 0000000..88d5ffb
--- /dev/null
@@ -0,0 +1,45 @@
+<project name="domctl project" default="compile">
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="dist" location="dist"/>
+  <property name="lib" location="lib"/>
+
+  <target name="init">
+    <tstamp/>
+    <mkdir dir="${build}"/>     
+  </target>
+
+  <target name="compile" depends="init">
+    <javac srcdir="${src}" destdir="${build}" debug="on"/>
+  </target>
+
+  <target name="dist" depends="compile">
+    <jar jarfile="domctl.jar"
+         excludes="*~"
+        basedir="${build}">
+      <fileset dir="${src}" />
+      <fileset dir=".">
+        <include name="build.xml"/>
+        <include name="domctl"/>
+      </fileset>
+      <manifest>
+        <attribute name="Built-By" value="${user.name}"/>
+       <attribute name="Main-Class" value="uk.ac.cam.cl.xeno.domctl.Main"/>
+       <attribute name="Sealed" value="true"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="test" depends="compile">
+    <java fork="true" classname="uk.ac.cam.cl.xeno.domctl.Main">
+      <classpath>
+        <pathelement path="${build}"/>
+      </classpath>
+    </java>
+  </target>
+
+  <target name="clean">
+    <delete dir="${build}"/>
+    <delete dir="${lib}"/>
+  </target>
+</project>
\ No newline at end of file
diff --git a/tools/domctl/domctl b/tools/domctl/domctl
new file mode 100755 (executable)
index 0000000..3f80d21
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/bash -x
+
+if [ -z "$DEFAULTS_FILE" ] ; then DEFAULTS_FILE=domctl.xml ; fi
+if [ -z "$DEFAULTS_PATH" ] ; then DEFAULTS_PATH=.:/etc ; fi
+if [ -z "$QUERY_DEV" ] ; then QUERY_DEV=eth0 ; fi
+if [ -z "$IFCONFIG" ] ; then IFCONFIG=/sbin/ifconfig ; fi
+if [ -z "$ROUTE" ] ; then ROUTE=/sbin/route ; fi
+if [ -z "$JAVA" ] ; then JAVA=java ; fi
+
+if [ ! -x "$IFCONFIG" ]; then
+  echo Could not find executable $IFCONFIG
+  exit 1
+fi
+
+if [ ! -x "$ROUTE" ]; then
+  echo Could not find executable $ROUTE
+  exit 1
+fi
+
+# Try to determine dom0 network settings to avoid hard-coding
+# particular machines in the defaults file
+LOCAL_IP=$(/sbin/ifconfig $QUERY_DEV | grep 'inet addr' | tr ':' '\t' | awk '{print $3}')
+LOCAL_MASK=$(/sbin/ifconfig $QUERY_DEV | grep 'Mask' | tr ':' '\t' | awk '{print $7}')
+LOCAL_ROUTE=$(/sbin/route -n | grep $QUERY_DEV | grep 'G' | awk '{print $2}')
+
+
+#ARGS="-DTEST -DDEFAULTS_FILE=$DEFAULTS_FILE -DDEFAULTS_PATH=$DEFAULTS_PATH -DLOCAL_IP=$LOCAL_IP -DLOCAL_MASK=$LOCAL_MASK -DLOCAL_ROUTE=$LOCAL_ROUTE"
+ARGS="-DDEFAULTS_FILE=$DEFAULTS_FILE -DDEFAULTS_PATH=$DEFAULTS_PATH -DLOCAL_IP=$LOCAL_IP -DLOCAL_MASK=$LOCAL_MASK -DLOCAL_ROUTE=$LOCAL_ROUTE"
+
+
+$JAVA $ARGS -jar domctl.jar $*
diff --git a/tools/domctl/domctl.xml b/tools/domctl/domctl.xml
new file mode 100644 (file)
index 0000000..168b8da
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<domctl_defaults>
+<domain_name>XenoLinux</domain_name>
+<domain_size_kb>16000</domain_size_kb>
+<domain_image>./image</domain_image>
+<domain_vifs>1</domain_vifs>
+<root_device>/dev/nfs</root_device>
+<nw_ip>=+</nw_ip>
+<nw_gw>=</nw_gw>
+<nw_mask>=</nw_mask>
+<nw_nfs_server>128.232.32.20</nw_nfs_server>
+<nw_nfs_root>/usr/groups/srgboot/moonraider/roots/root+</nw_nfs_root>
+<max_domain_number>2</max_domain_number>
+<xi_tools_dir>/tools/internal/</xi_tools_dir>
+</domctl_defaults>
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Command.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Command.java
new file mode 100644 (file)
index 0000000..b667e3f
--- /dev/null
@@ -0,0 +1,74 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+public abstract class Command
+{
+  public abstract int doCommand(Defaults d, String args[]);
+  public abstract String getName();                    
+  public abstract String getUsage();
+  public abstract String getHelpText();
+
+  public String getStringParameter(String args[], char key, String def)
+  {
+    String r = getParameter (args, key);
+    return (r == null) ? def : r;
+  }
+
+  public int getIntParameter(String args[], char key, int def)
+  {
+    String r = getParameter (args, key);
+    return (r == null) ? def : (Integer.parseInt (r));
+  }
+
+  public boolean getFlagParameter(String args[], char key)
+  {
+    String r = getParameter (args, key);
+    return (r == null) ? false : true;
+  }
+
+  public String getParameter (String args[], char key)
+  {
+    int i;
+    String result = null;
+    for (i = 0; i < args.length; i ++)
+      {
+       if (args[i].startsWith("-" + key)) 
+         {
+           if (args[i].length() > 2)
+             {
+               result = args[i].substring(2, args[i].length());
+             }
+           else
+             {
+               result = "";
+             }
+         }
+      }
+    return result;
+  }
+
+  public int reportXIError (String message, String cmd_array[])
+  {
+    int i;
+    System.err.print (message + " using: ");
+    for (i = 0; i < cmd_array.length; i ++) {
+      System.err.print (cmd_array[i] + " ");
+    }
+    System.err.println();
+    return -1;
+  }
+
+  public int reportError (String message)
+  {
+    System.err.println (message);
+    return -1;
+  }
+
+  public void reportCommand (String cmd_array[])
+  {
+    int i;
+    for (i = 0; i < cmd_array.length; i ++) {
+      System.out.print (cmd_array[i] + " ");
+    }
+    System.out.println();
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandDestroy.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandDestroy.java
new file mode 100644 (file)
index 0000000..025f373
--- /dev/null
@@ -0,0 +1,69 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.io.*;
+import java.net.*;
+
+public class CommandDestroy extends Command
+{
+  public int doCommand(Defaults d, String args[])
+  {
+    Runtime r = Runtime.getRuntime ();
+    int domain_id = getIntParameter(args, 'n', 0);
+    boolean force = getFlagParameter(args, 'f');
+    int rc = 0;
+
+    if (domain_id == 0) {
+      System.err.println ("Expected -n<domain_id>");
+      rc = -1;
+      return rc;
+    }
+
+    try
+      {
+       Process destroy_p;
+       String destroy_cmdarray[] = force ? new String[3] : new String[2];
+       int destroy_rc;
+       int idx = 0;
+       destroy_cmdarray[idx++] = d.XIToolsDir + "xi_destroy";
+       if (force) {
+         destroy_cmdarray[idx++] = "-f";
+       }
+       destroy_cmdarray[idx++] = "" + domain_id;
+
+       if (Settings.TEST) {
+         reportCommand (destroy_cmdarray);
+       } else {
+         destroy_p = r.exec (destroy_cmdarray);
+         destroy_rc = destroy_p.waitFor ();
+         
+         if (destroy_rc != 0) {
+           return reportXIError ("Could not destroy domain", destroy_cmdarray);
+         }
+       }
+      }
+    catch (Exception e) 
+      {
+       System.err.println ("Could not destroy domain (" + e + ")");
+       e.printStackTrace ();
+       rc = -1;
+      }
+
+    return rc;
+  }
+
+  public String getName()
+  {
+    return "destroy";
+  }
+
+  public String getUsage()
+  {
+    return "[-f] [-n<domain_id>]";
+  }
+
+  public String getHelpText()
+  {
+    return
+      "Destory the specified domain.  -f forcibly destroys it.";
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandHelp.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandHelp.java
new file mode 100644 (file)
index 0000000..aef1ee9
--- /dev/null
@@ -0,0 +1,58 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+public class CommandHelp extends Command
+{
+  public int doCommand(Defaults d, String args[])
+  {
+    if (args.length <= 1)
+      {
+       System.out.println ("Usage:");
+       for (int i = 0; i < Main.commands.length; i ++) 
+         {
+           String name = Main.commands[i].getName ();
+           String usage = Main.commands[i].getUsage ();
+           while (name.length() < 12) name = name + " ";
+           System.out.println ("   " + name + usage);
+         }
+      }
+    else 
+      {
+       for (int i = 0; i < Main.commands.length; i ++) 
+         {
+           String name = Main.commands[i].getName ();
+           String usage = Main.commands[i].getUsage ();
+           if (name.equals (args[1]))
+             {
+               doHelpFor (Main.commands[i]);
+               break;
+             }
+         }
+      }
+
+    System.out.println ("");
+    return 0;
+  }
+
+  public int doHelpFor (Command c)
+  {
+    System.out.println ("domctl " + c.getName() + " " + c.getUsage());
+    System.out.println ();
+    System.out.println (c.getHelpText ());
+    return 0;
+  }
+
+  public String getName()
+  {
+    return "help";
+  }
+
+  public String getUsage()
+  {
+    return "";
+  }
+
+  public String getHelpText()
+  {
+    return "This message";
+  }  
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandNew.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandNew.java
new file mode 100644 (file)
index 0000000..1dd9156
--- /dev/null
@@ -0,0 +1,203 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.io.*;
+import java.net.*;
+
+public class CommandNew extends Command
+{
+  public int doCommand(Defaults d, String args[])
+  {
+    Runtime r = Runtime.getRuntime ();
+    String name = getStringParameter(args, 'n', d.domainName);
+    int size = getIntParameter(args, 'k', d.domainSizeKB);
+    String image = getStringParameter(args, 'i', d.domainImage);
+    String initrd = getStringParameter (args, 'r', d.domainInitRD);
+    int vifs = getIntParameter(args, 'v', d.domainVIFs);
+    String bargs = getStringParameter (args, 'a', "");
+    String root_dev = getStringParameter (args, 'd', d.rootDevice);
+    String nfs_root_path = getStringParameter (args, 'f', d.NWNFSRoot);
+    String nw_ip = getStringParameter (args, '4', d.NWIP);
+    String nw_gw = getStringParameter (args, 'g', d.NWGW);
+    String nw_mask = getStringParameter (args, 'm', d.NWMask);
+    String nw_nfs_server = getStringParameter (args, 's', d.NWNFSServer);
+    String nw_host = getStringParameter (args, 'h', d.NWHost);
+    String domain_ip = "";
+    int rc = 0;
+    int domain_id;
+    DataInputStream dis;
+    int idx;
+    int i;
+
+
+    try
+      {
+       /* Some initial sanity checks */
+       if (root_dev.equals ("/dev/nfs") && (vifs == 0)) {
+         return reportError ("Cannot use NFS root without VIFs configured");
+       }
+
+       /* Create a new empty domain */
+       Process create_p;
+       String create_cmdarray[] = new String[3];
+       int create_rc;
+       create_cmdarray[0] = d.XIToolsDir + "xi_create";
+       create_cmdarray[1] = "" + size;
+       create_cmdarray[2] = name;
+       if (Settings.TEST) {
+         reportCommand (create_cmdarray);
+         domain_id=1;
+         create_rc=0;
+       } else {
+         create_p = r.exec (create_cmdarray);
+         dis = new DataInputStream (new BufferedInputStream (create_p.getInputStream ()));
+         domain_id = Integer.parseInt (dis.readLine ());
+         create_rc = create_p.waitFor ();
+       }
+
+       if (create_rc != 0) {
+         return reportXIError ("Failed to create domain", create_cmdarray);
+       } else if (domain_id > d.MaxDomainNumber) {
+         return reportError ("Cannot configure more than " + 
+                             d.MaxDomainNumber + " domains");
+       }
+       
+       /* Set up boot parameters to pass to xi_build. */
+       bargs = "";
+
+       if (root_dev.equals ("/dev/nfs")) {
+         if (vifs == 0) {
+           return reportError ("Cannot use NFS root without VIFs configured");
+         }
+         bargs = (bargs + 
+                  "root=/dev/nfs " +
+                  "nfsroot=" + StringPattern.parse(nfs_root_path).resolve(domain_id) +
+                  " ");
+       } else {
+         bargs = ("root=" + StringPattern.parse(root_dev).resolve(domain_id) +
+                  " ");
+
+       }
+       
+       if (vifs > 0) {
+         domain_ip = InetAddressPattern.parse(nw_ip).resolve(domain_id);
+         if (nw_host == null) {
+           try {
+             nw_host = InetAddress.getByName(domain_ip).getHostName();
+           } catch (UnknownHostException uhe) {
+             nw_host = "" + nw_ip;
+           }
+           
+         }
+         bargs = ("ip=" + domain_ip +
+                  ":" + InetAddressPattern.parse(nw_nfs_server).resolve(domain_id) +
+                  ":" + InetAddressPattern.parse(nw_gw).resolve(domain_id) + 
+                  ":" + InetAddressPattern.parse(nw_mask).resolve(domain_id) +
+                  ":" + nw_host + 
+                  ":eth0:off " + bargs);
+       }
+       
+       /* Build the domain */
+       Process build_p;
+       String build_cmdarray[] = new String[6];
+       int build_rc;
+       idx = 0;
+       for (i = 0; i < build_cmdarray.length; i ++) 
+         build_cmdarray[i] = "";
+       build_cmdarray[idx ++] = d.XIToolsDir + "xi_build";
+       build_cmdarray[idx ++] = "" + domain_id;
+       build_cmdarray[idx ++] = "" + image;
+       build_cmdarray[idx ++] = "" + vifs;
+       if (initrd != null) build_cmdarray[idx ++] = "initrd=" + initrd;
+       build_cmdarray[idx ++] = "" + bargs;
+       System.out.println ("Build args: " + bargs);
+       if (Settings.TEST) {
+         reportCommand (build_cmdarray);
+         build_rc = 0;
+       } else {
+         build_p = r.exec (build_cmdarray);
+         build_rc = build_p.waitFor ();
+       }
+
+       if (build_rc != 0) {
+         return reportXIError ("Failed to build domain", build_cmdarray);
+       }
+
+
+       /* Set up the first VIF if necessary */
+       if (vifs > 0) {
+         Process vifinit_p;
+         String vifinit_cmdarray[] = new String[4];
+         int vifinit_rc;
+         vifinit_cmdarray[0] = d.XIToolsDir + "xi_vifinit";
+         vifinit_cmdarray[1] = "" + domain_id;
+         vifinit_cmdarray[2] = "0";
+         vifinit_cmdarray[3] = domain_ip;
+         if (Settings.TEST) {
+           reportCommand (vifinit_cmdarray);
+           vifinit_rc = 0;
+         } else {
+           vifinit_p = r.exec (vifinit_cmdarray);
+           vifinit_rc = vifinit_p.waitFor ();
+         }
+         
+         if (vifinit_rc != 0) {
+           return reportXIError ("Failed to initialise VIF 0", vifinit_cmdarray);
+         }
+       }
+      }
+    catch (Exception e) 
+      {
+       System.err.println ("Could not create new domain (" + e + ")");
+       e.printStackTrace ();
+       rc = -1;
+      }
+
+    return rc;
+  }
+
+  public String getName()
+  {
+    return "new";
+  }
+
+  public String getUsage()
+  {
+    return "[-n<domain_name>] [-k<size>] [-i<image>] [-v<num_vifs>] [-r<initrd>] [-d<root_device>] [-f<nfs_root>] [-s<nfs_boot_server>] [-4<ipv4_boot_address>] [-g<ipv4_boot_gateway>] [-m<ipv4_boot_netmask>] [-h<hostname>] [-a<args>]";
+  }
+
+  public String getHelpText()
+  {
+    return
+      "Create a new domain.  Note that most of the parameters will assume\n" +
+      "default values: it should not be necessary to specify them all. See\n" +
+      "domctl.xml for the current default settings.\n" +
+      "\n" +
+      "General command line options:\n" +
+      "  -n  Domain name                              domain_name\n" +
+      "  -k  Domain size (kb)                         domain_size_kb\n" +
+      "  -i  Domain image name                        domain_image\n" +
+      "  -v  Number of VIFs                           domain_vifs\n" +
+      "  -r  InitRD (if required)                     domain_init_rd\n" +
+      "  -d  Root device (e.g /dev/nfs, /dev/hda3)    root_device\n" +
+      "  -a  Additional boot parameters\n" +
+      "\n" +
+      "Networking options:\n" +
+      "  -f  NFS root (if /dev/nfs specified)         nw_nfs_root\n" +
+      "  -s  NFS server                               nw_nfs_server\n" +
+      "  -4  Domain IPv4 address                      nw_ip\n" +
+      "  -g  Domain gateway                           nw_gw\n" +
+      "  -m  Domain net mask                          nw_mask\n" +
+      "  -h  Domain hostname                          nw_host\n" +
+      "\n" +
+      "Parameters to -d, -f, -4, -g, -h can be specified as patterns into\n" +
+      "which the allocated domain ID will be incorporated.  e.g.  for\n" +
+      "domain 1 patterns would expand as follows:\n" +
+      "\n" +
+      "  /dev/hda+       /dev/hda1\n" +
+      "  /dev/hda7+      /dev/hda8\n" +
+      "  128.232.8.50+   128.232.8.51\n" +
+      "\n" +
+      "Additionally, patterns for -4 -g -m can include an = which is\n" + 
+      "expanded to the corresponding setting from the calling domain.\n";
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStart.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStart.java
new file mode 100644 (file)
index 0000000..b84b66d
--- /dev/null
@@ -0,0 +1,63 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.io.*;
+import java.net.*;
+
+public class CommandStart extends Command
+{
+  public int doCommand(Defaults d, String args[])
+  {
+    Runtime r = Runtime.getRuntime ();
+    int domain_id = getIntParameter(args, 'n', 0);
+    int rc = 0;
+
+    if (domain_id == 0) {
+      System.err.println ("Expected -n<domain_id>");
+      rc = -1;
+      return rc;
+    }
+
+    try
+      {
+       Process start_p;
+       String start_cmdarray[] = new String[2];
+       int start_rc;
+       start_cmdarray[0] = d.XIToolsDir + "xi_start";
+       start_cmdarray[1] = "" + domain_id;
+
+       if (Settings.TEST) {
+         reportCommand (start_cmdarray);
+       } else {
+         start_p = r.exec (start_cmdarray);
+         start_rc = start_p.waitFor ();
+         if (start_rc != 0) {
+           return reportXIError ("Could not start domain", start_cmdarray);
+         }
+       }
+      }
+    catch (Exception e) 
+      {
+       System.err.println ("Could not start new domain (" + e + ")");
+       e.printStackTrace ();
+       rc = -1;
+      }
+
+    return rc;
+  }
+
+  public String getName()
+  {
+    return "start";
+  }
+
+  public String getUsage()
+  {
+    return "[-n<domain_id>]";
+  }
+
+  public String getHelpText()
+  {
+    return
+      "Start the specified domain.";
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStop.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/CommandStop.java
new file mode 100644 (file)
index 0000000..c6b4cad
--- /dev/null
@@ -0,0 +1,64 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.io.*;
+import java.net.*;
+
+public class CommandStop extends Command
+{
+  public int doCommand(Defaults d, String args[])
+  {
+    Runtime r = Runtime.getRuntime ();
+    int domain_id = getIntParameter(args, 'n', 0);
+    int rc = 0;
+
+    if (domain_id == 0) {
+      System.err.println ("Expected -n<domain_id>");
+      rc = -1;
+      return rc;
+    }
+
+    try
+      {
+       Process stop_p;
+       String stop_cmdarray[] = new String[2];
+       int stop_rc;
+       stop_cmdarray[0] = d.XIToolsDir + "xi_stop";
+       stop_cmdarray[1] = "" + domain_id;
+
+       if (Settings.TEST) {
+         reportCommand (stop_cmdarray);
+       } else {
+         stop_p = r.exec (stop_cmdarray);
+         stop_rc = stop_p.waitFor ();
+         
+         if (stop_rc != 0) {
+           return reportXIError ("Could not stop domain", stop_cmdarray);
+         }
+       }
+      }
+    catch (Exception e) 
+      {
+       System.err.println ("Could not stop new domain (" + e + ")");
+       e.printStackTrace ();
+       rc = -1;
+      }
+
+    return rc;
+  }
+
+  public String getName()
+  {
+    return "stop";
+  }
+
+  public String getUsage()
+  {
+    return "[-n<domain_id>]";
+  }
+
+  public String getHelpText()
+  {
+    return
+      "Stop the specified domain.";
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Defaults.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Defaults.java
new file mode 100644 (file)
index 0000000..bacce11
--- /dev/null
@@ -0,0 +1,153 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.net.InetAddress;
+import java.io.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+public class Defaults
+{
+  String domainName;
+
+  int domainSizeKB;
+  String domainImage;
+  String domainInitRD;
+  int domainVIFs;
+
+  String rootDevice;
+
+  String NWIP;
+  String NWGW;
+  String NWMask;
+  String NWHost;
+
+  String NWNFSServer;
+  String NWNFSRoot;
+
+  int MaxDomainNumber;
+
+  String XIToolsDir;
+
+  /***********************************************************************/
+
+  public Defaults ()
+  {
+    File f = Settings.getDefaultsFile ();
+    System.out.println ("f=" + f);
+
+    try
+      {
+       XMLReader xr = new org.apache.crimson.parser.XMLReaderImpl();
+       Handler handler = new Handler ();
+       xr.setContentHandler (handler);
+       xr.setErrorHandler (handler);
+       xr.parse (new InputSource(new FileReader (f)));
+      }
+    catch (Exception e) 
+      {
+       System.err.println ("Could not read defaults file " + f +
+                           "\nException: " + e);
+       e.printStackTrace();
+       System.exit(1);
+      }
+
+    System.out.println ("Domain defaults:");
+    System.out.println ("   name        " + domainName);
+    System.out.println ("   size        " + domainSizeKB);
+    System.out.println ("   vifs        " + domainVIFs);
+    System.out.println ("   domainImage " + domainImage);
+    System.out.println ("   domainInitRD " + domainInitRD);
+    System.out.println ("   rootDevice " + rootDevice);
+    System.out.println ("   NWIP " + NWIP);
+    System.out.println ("   NWGW " + NWGW);
+    System.out.println ("   NWMask " + NWMask);
+    System.out.println ("   MaxDomainNumber " + MaxDomainNumber);
+    System.out.println ("   NWNFSServer " + NWNFSServer);
+    System.out.println ("   NWNFSRoot " + NWNFSRoot);
+    System.out.println ("   XIToolsDir " + XIToolsDir);
+  }
+
+  /***********************************************************************/
+
+  class Handler extends DefaultHandler
+  {
+    boolean inDomctlDefaults;
+    String lastName;
+
+    public void startDocument ()
+    {
+    }
+
+    public void endDocument ()
+    {
+    }
+
+    public void startElement (String uri, String name,
+                             String qname, Attributes atts)
+    {
+      if (qname.equals ("domctl_defaults")) {
+       inDomctlDefaults = true;
+      } else {
+       lastName = qname;
+      }
+    }
+
+    public void endElement (String uri, String name, String qname)
+    {
+      lastName = "";
+      if (qname.equals ("domctl_defaults")) {
+       inDomctlDefaults = false;
+      }
+    }
+    
+    public void characters (char ch[], int start, int length)
+    {
+      String s = new String (ch, start, length);
+      if (lastName != null)
+       {
+         if (lastName.equals ("domain_size_kb")) {
+           domainSizeKB = Integer.parseInt (s);
+         } else if (lastName.equals ("domain_image")) {
+           domainImage = s;
+         } else if (lastName.equals ("domain_name")) {
+           domainName = s;
+         } else if (lastName.equals ("domain_init_rd")) {
+           domainInitRD = s;
+         } else if (lastName.equals ("domain_vifs")) {
+           domainVIFs = Integer.parseInt (s);
+         } else if (lastName.equals ("root_device")) {
+           rootDevice = s;
+         } else if (lastName.equals ("nw_ip")) {
+           NWIP = expandDefault (s, Settings.LOCAL_IP);
+         } else if (lastName.equals ("nw_gw")) {
+           NWGW = expandDefault (s, Settings.LOCAL_GW);
+         } else if (lastName.equals ("nw_mask")) {
+           NWMask = expandDefault (s, Settings.LOCAL_MASK);
+         } else if (lastName.equals ("nw_host")) {
+           NWHost = s;
+         } else if (lastName.equals ("nw_nfs_server")) {
+           NWNFSServer = s;
+         } else if (lastName.equals ("nw_nfs_root")) {
+           NWNFSRoot = s;
+         } else if (lastName.equals ("max_domain_number")) {
+           MaxDomainNumber = Integer.parseInt(s);
+         } else if (lastName.equals ("xi_tools_dir")) {
+           XIToolsDir = s;
+         }
+       }
+    }
+  }
+
+  public String expandDefault (String supplied, String self)
+  {
+    if (supplied.startsWith ("=")) {
+      if (supplied.length() > 1) {
+       return self + supplied.substring (1, supplied.length());
+      } else {
+       return self;
+      }
+    } else {
+      return supplied;
+    }
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/InetAddressPattern.java
new file mode 100644 (file)
index 0000000..5786edd
--- /dev/null
@@ -0,0 +1,60 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.net.*;
+
+public class InetAddressPattern
+{
+  InetAddress base;
+  boolean addDom;
+
+  static InetAddressPattern parse (String t)
+  {
+    InetAddressPattern result = new InetAddressPattern ();
+    char[] ca = t.toCharArray ();
+    int idx = 0;
+    int len = ca.length;
+
+    try {
+      if (len == 0) {
+       result.base = null;
+       result.addDom = false;
+      } else if (ca[len - 1] == '+') {
+       result.base = InetAddress.getByName(t.substring(0, len - 1));
+       result.addDom = true;
+      } else {
+       result.base = InetAddress.getByName(t);
+       result.addDom = false;
+      }
+    } catch (UnknownHostException uhe) {
+      result.base = null;
+      result.addDom = false;
+    }
+
+    return result;
+  }
+
+  public String resolve (int domain_id) {
+    byte b[] = base.getAddress ();
+    if (addDom) {
+      if (((int)b[3]) + domain_id > 255) {
+       if (((int)b[2]) + domain_id > 255) {
+         if (((int)b[1]) + domain_id > 255) {
+           b[0] ++;
+         }
+         b[1] ++;
+       }
+       b[2] ++;
+      }
+      b[3] += domain_id;
+    }
+    return "" + 
+      (b[0] + (b[0] < 0 ? 256 : 0)) + "." + 
+      (b[1] + (b[1] < 0 ? 256 : 0)) + "." + 
+      (b[2] + (b[2] < 0 ? 256 : 0)) + "." + 
+      (b[3] + (b[3] < 0 ? 256 : 0));
+  }
+
+  public String toString () {
+    return "[" + base + (addDom ? "+dom_id" : "") + "]";
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Main.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Main.java
new file mode 100644 (file)
index 0000000..49b4fb3
--- /dev/null
@@ -0,0 +1,39 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+public class Main 
+{
+  static CommandHelp help = new CommandHelp ();
+  static CommandNew newdom = new CommandNew ();
+  static CommandStart start = new CommandStart ();
+  static CommandStop stop = new CommandStop ();
+  static CommandDestroy destroy = new CommandDestroy ();
+  static Command commands[] = { help, newdom, start, stop, destroy };
+
+  public static void main (String[] args)
+  {
+    Defaults d = new Defaults ();
+    int ec = -1;
+
+    if (args.length == 0) {
+      ec = help.doCommand (d, args);
+    } else {
+      String c = args[0];
+      int i;
+      for (i = 0; i < commands.length; i ++) {
+       if (commands[i].getName().equals(c)) {
+         if (commands[i].getFlagParameter (args, '?')) {
+           ec = help.doHelpFor (commands[i]);
+         } else {
+           ec = commands[i].doCommand (d, args);
+         }
+         break;
+       }
+      }
+      if (i == commands.length) {
+       System.out.println ("Unknown command " + c);
+      }
+    }
+
+    System.exit (ec);
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Settings.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/Settings.java
new file mode 100644 (file)
index 0000000..13d1a2d
--- /dev/null
@@ -0,0 +1,38 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+import java.util.*;
+import java.io.*;
+import org.xml.sax.*;
+
+public final class Settings
+{
+  public static final String DEFAULTS_FILE = System.getProperty ("DEFAULTS_FILE");
+  public static final String DEFAULTS_PATH = System.getProperty ("DEFAULTS_PATH");
+  public static final String LOCAL_IP = System.getProperty ("LOCAL_IP");
+  public static final String LOCAL_MASK = System.getProperty ("LOCAL_MASK");
+  public static final String LOCAL_GW = System.getProperty ("LOCAL_ROUTE");
+  public static final boolean TEST = (System.getProperty ("TEST") != null);
+
+
+  public static File getDefaultsFile() {
+    StringTokenizer tok = new StringTokenizer (DEFAULTS_PATH, ":");
+    File result = null;
+    File probe;
+
+    while (tok.hasMoreTokens ()) {
+      String probe_dir = tok.nextToken ();
+      probe = new File (probe_dir, DEFAULTS_FILE);
+      if (probe.exists ()) {
+       result = probe;
+       break;
+      }
+    }
+
+    if (result == null) {
+      System.err.println ("Could not find " + DEFAULTS_FILE + " in path " + DEFAULTS_PATH);
+      System.exit (1);
+    }
+
+    return result;
+  }
+}
diff --git a/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/StringPattern.java b/tools/domctl/src/uk/ac/cam/cl/xeno/domctl/StringPattern.java
new file mode 100644 (file)
index 0000000..a0486ba
--- /dev/null
@@ -0,0 +1,59 @@
+package uk.ac.cam.cl.xeno.domctl;
+
+public class StringPattern
+{
+  String base;
+  int bn;
+  boolean addDom;
+  boolean appendDom;
+
+  static StringPattern parse (String t)
+  {
+    StringPattern result = new StringPattern ();
+    char[] ca = t.toCharArray ();
+    int idx = 0;
+    int len = ca.length;
+
+    if (len == 0) {
+      result.base = "";
+      result.bn = 0;
+      result.addDom = false;
+    } else if (ca[len - 1] == '+') {
+      idx = len - 2;
+      if ((idx >= 0) && (ca[idx] >= '0') && (ca[idx] <= '9')) {
+       while ((idx >= 0) && (ca[idx] >= '0') && (ca[idx] <= '9')) {
+         idx --;
+       }
+       result.base = t.substring(0, idx + 1);
+       result.bn = Integer.parseInt (t.substring (idx + 1, len - 1));
+       result.addDom = true;
+      } else {
+       result.base = t.substring(0, len - 1);
+       result.appendDom = true;
+      }
+    } else {
+      result.base = t;
+    }
+
+    return result;
+  }
+
+  public String resolve (int domain_id) {
+    if (addDom) {
+      return base + (bn + domain_id);
+    } else if (appendDom) {
+      return base + domain_id;
+    } else {
+      return base;
+    }
+  }
+
+  public String toString () {
+    return ("[" + 
+           base + 
+           (addDom ? "+" + bn : "") + 
+           ((addDom || appendDom) ? "+ID" : "") + 
+           "]");
+  }
+
+}
diff --git a/tools/internal/Makefile b/tools/internal/Makefile
new file mode 100644 (file)
index 0000000..d2e1922
--- /dev/null
@@ -0,0 +1,32 @@
+CC = gcc
+XI_CREATE = xi_create
+XI_START = xi_start
+XI_STOP = xi_stop
+XI_DESTROY = xi_destroy
+XI_BUILD = xi_build
+
+all: $(XI_CREATE).o $(XI_START).o $(XI_STOP).o $(XI_DESTROY).o $(XI_BUILD).o
+       $(CC) -o $(XI_CREATE) $(XI_CREATE).o
+       $(CC) -o $(XI_BUILD) $(XI_BUILD).o
+       $(CC) -o $(XI_START) $(XI_START).o
+       $(CC) -o $(XI_STOP) $(XI_STOP).o
+       $(CC) -o $(XI_DESTROY) $(XI_DESTROY).o
+
+$(XI_CREATE).o: $(XI_CREATE).c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h
+       $(CC) -c $(XI_CREATE).c 
+
+internal_domain_build.o: internal_domain_build.c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h
+       $(CC) -c internal_domain_build.c 
+
+$(XI_START).o: $(XI_START).c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h
+       $(CC) -c $(XI_START).c 
+
+$(XI_STOP).o: $(XI_STOP).c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h
+       $(CC) -c $(XI_STOP).c 
+
+$(XI_DESTROY).o: $(XI_DESTROY).c dom0_ops.h dom0_defs.h
+       $(CC) -c $(XI_DESTROY).c 
+
+clean:
+       $(RM) *.o $(XI_CREATE) $(XI_START) $(XI_STOP) $(XI_DESTROY) $(XI_BUILD)
+
diff --git a/tools/internal/dom0_defs.h b/tools/internal/dom0_defs.h
new file mode 100644 (file)
index 0000000..e79d85d
--- /dev/null
@@ -0,0 +1,9 @@
+#define PROC_XENO_ROOT  "xeno"
+#define PROC_CMD        "dom0_cmd"
+#define PROC_DOM_PREFIX "dom"
+#define PROC_DOM_MEM    "mem"
+#define PROC_DOM_DATA   "new_dom_data"
+#define PROC_DOMAINS    "domains"
+
+#define MAX_PATH        256
+
diff --git a/tools/internal/hypervisor_defs.h b/tools/internal/hypervisor_defs.h
new file mode 100644 (file)
index 0000000..7d0aba0
--- /dev/null
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * hypervisor_defs.h
+ * 
+ * This needs to be kept in sync with Xen's pagetable update interface!
+ * 
+ * Copyright (c) 2002-2003, Keir Fraser & Boris Dragovic 
+ */
+
+/* taken from include/hypervisor-ifs/hypervisor-if.h */
+typedef struct
+{
+/*
+ * PGREQ_XXX: specified in least-significant bits of 'ptr' field. All requests 
+ * specify relevent PTE or PT address in 'ptr'. Normal requests specify update 
+ * value in 'value'. Extended requests specify command in least 8 bits of 
+ * 'value'.
+ */
+    unsigned long ptr, val; /* *ptr = val */
+} page_update_request_t;
+
+/* A normal page-table update request. */
+#define PGREQ_NORMAL           0
+#define PGREQ_MPT_UPDATE 1
+/* An extended command. */
+#define PGREQ_EXTENDED_COMMAND 2
+/* Announce a new top-level page table. */
+#define PGEXT_PIN_L1_TABLE      0
+#define PGEXT_PIN_L2_TABLE      1
+#define PGEXT_PIN_L3_TABLE      2
+#define PGEXT_PIN_L4_TABLE      3
+#define PGEXT_UNPIN_TABLE       4
+#define PGEXT_NEW_BASEPTR       5
+#define PGEXT_TLB_FLUSH         6
+#define PGEXT_INVLPG            7
+#define PGEXT_CMD_MASK        255
+#define PGEXT_CMD_SHIFT         8
diff --git a/tools/internal/mem_defs.h b/tools/internal/mem_defs.h
new file mode 100644 (file)
index 0000000..a9a1441
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * memory related definitions needed for userspace domain builder dom0 application. these _need_ to
+ * be kept in sync with the kernel .h files they were copied over from or something horrible will
+ * happen. remmember: god kills a kitten every time you forget to keep these in sync.
+ * 
+ * KAF: Boris, these constants are all fixed by x86 hardware. So the kittens are safe for now :-)
+ * 
+ * Copyright 2002 by B Dragovic
+ */
+
+/* copied over from hypervisor: include/asm-i386/page.h */
+
+#define _PAGE_PRESENT   0x001
+#define _PAGE_RW    0x002
+#define _PAGE_USER  0x004
+#define _PAGE_PWT   0x008
+#define _PAGE_PCD   0x010
+#define _PAGE_ACCESSED  0x020
+#define _PAGE_DIRTY 0x040
+#define _PAGE_PAT       0x080
+#define _PAGE_PSE   0x080
+#define _PAGE_GLOBAL    0x100
+
+
+#define L1_PAGETABLE_SHIFT       12
+#define L2_PAGETABLE_SHIFT       22
+#define ENTRIES_PER_L1_PAGETABLE 1024
+#define ENTRIES_PER_L2_PAGETABLE 1024
+#define PAGE_SHIFT              L1_PAGETABLE_SHIFT
+#define PAGE_SIZE               (1UL << PAGE_SHIFT)
+#define PAGE_MASK               (~(PAGE_SIZE-1))
+
+typedef struct { unsigned long l1_lo; } l1_pgentry_t;
+typedef struct { unsigned long l2_lo; } l2_pgentry_t;
+
+#define l1_table_offset(_a) \
+          (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
+#define l2_table_offset(_a) \
+          ((_a) >> L2_PAGETABLE_SHIFT)
+
+/* local definitions */
+
+#define nr_2_page(x) (x << PAGE_SHIFT)
diff --git a/tools/internal/xi_build.c b/tools/internal/xi_build.c
new file mode 100644 (file)
index 0000000..2df44f6
--- /dev/null
@@ -0,0 +1,524 @@
+/* 
+ * XenoDomainBuilder, copyright (c) Boris Dragovic, bd240@cl.cam.ac.uk
+ * This code is released under terms and conditions of GNU GPL :).
+ * Usage: <executable> <mem_kb> <os image> <num_vifs> 
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "hypervisor_defs.h"
+#include "dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+#define PERR_STRING "Xeno Domain Builder"
+
+#define GUEST_SIG   "XenoGues"
+#define SIG_LEN    8
+
+/*
+ * NB. No ring-3 access in initial guestOS pagetables. Note that we allow
+ * ring-3 privileges in the page directories, so that the guestOS may later
+ * decide to share a 4MB region with applications.
+ */
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
+#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+
+/* standardized error reporting function */
+static void dberr(char *msg)
+{
+    printf("%s: %s\n", PERR_STRING, msg);
+}
+
+/* status reporting function */
+static void dbstatus(char * msg)
+{
+    printf("Domain Builder: %s\n", msg);
+}
+
+
+/* clean up domain's memory allocations */
+static void dom_mem_cleanup(dom_mem_t * dom_mem)
+{
+    char mem_path[MAX_PATH];
+    int mem_fd;
+
+    /* open the domain's /proc mem interface */
+    sprintf(mem_path, "%s%s%s%s%d%s%s", "/proc/", PROC_XENO_ROOT, "/", 
+        PROC_DOM_PREFIX, dom_mem->domain, "/", PROC_DOM_MEM);
+
+    mem_fd = open(mem_path, O_WRONLY);
+    if(mem_fd < 0){
+        perror(PERR_STRING);
+    }
+    
+    if(write(mem_fd, (dom_mem_t *)dom_mem, sizeof(dom_mem_t)) < 0){
+       dbstatus("Error unmapping domain's memory.\n");
+    }
+
+    close(mem_fd);
+}
+
+/* ask dom0 to export domains memory through /proc */
+static int setup_dom_memmap(unsigned long pfn, int pages, int dom)
+{
+    char cmd_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+
+    dop.cmd = MAP_DOM_MEM;
+    dop.u.dommem.start_pfn = pfn;
+    dop.u.dommem.tot_pages = pages;
+    dop.u.dommem.domain = dom;
+
+    /* open the /proc command interface */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        perror(PERR_STRING);
+        return -1;
+    }
+
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    return 0;
+}
+      
+/* request the actual mapping from dom0 */
+static unsigned long get_vaddr(unsigned int dom)
+{
+    char mem_path[MAX_PATH];
+       unsigned long addr;
+    int mem_fd;
+
+    /* open the domain's /proc mem interface */
+    sprintf(mem_path, "%s%s%s%s%d%s%s", "/proc/", PROC_XENO_ROOT, "/", 
+                    PROC_DOM_PREFIX, dom, "/", PROC_DOM_MEM);
+
+    mem_fd = open(mem_path, O_RDONLY);
+    if(mem_fd < 0){
+        perror(PERR_STRING);
+        return 0;
+    }
+
+    /* get virtual address of mapped region */
+       read(mem_fd, &addr, sizeof(addr));
+       
+    close(mem_fd);
+
+    return addr;
+}
+
+static int map_dom_mem(unsigned long pfn, int pages, int dom, 
+    dom_mem_t * dom_mem)
+{
+
+    if(setup_dom_memmap(pfn, pages, dom)){
+        perror(PERR_STRING);
+        return -1;
+    }
+
+    dom_mem->domain = dom;
+    dom_mem->start_pfn = pfn;
+    dom_mem->tot_pages = pages;
+    if((dom_mem->vaddr = get_vaddr(dom)) == 0){
+        dberr("Error mapping dom memory.");
+        return -1;
+    }
+    
+    return 0;
+}
+
+/* open kernel image and do some sanity checks */
+static int do_kernel_chcks(char *image, long dom_size, 
+    unsigned long * load_addr, size_t * ksize)
+{
+    char signature[8];
+    char status[MAX_PATH];
+    struct stat stat;
+    int fd;
+    int ret; 
+    
+    fd = open(image, O_RDONLY);
+    if(fd < 0){
+        perror(PERR_STRING);
+        ret = -1;    
+        goto out;
+    }
+
+    if(fstat(fd, &stat) < 0){
+        perror(PERR_STRING);
+        ret = -1;
+               close(fd);
+        goto out;
+    }
+
+    if(stat.st_size > (dom_size << 10)){
+        sprintf(status, "Kernel image size %ld larger than requested "
+            "domain size %ld\n Terminated.\n", stat.st_size, dom_size);
+        dberr(status);
+        ret = -1;
+               close(fd);
+        goto out;
+    }
+    
+    read(fd, signature, SIG_LEN);
+    if(strncmp(signature, GUEST_SIG, SIG_LEN)){
+        dberr("Kernel image does not contain required signature. "
+               "Terminating.\n");
+        ret = -1;
+               close(fd);
+        goto out;
+    }
+
+    read(fd, load_addr, sizeof(unsigned long));
+
+    *ksize = stat.st_size - SIG_LEN - sizeof(unsigned long);
+
+    ret = fd;
+
+out:    
+    return ret;
+}
+
+/* this is the main guestos setup function,
+ * returnes domain descriptor structure to be used when launching
+ * the domain by hypervisor to do some last minute initialization.
+ * page table initialization is done by making a list of page table
+ * requests that are handeled by the hypervisor in the ordinary
+ * manner. this way, many potentially messy things are avoided...
+ */ 
+#define PAGE_TO_VADDR(_pfn) ((void *)(dom_mem->vaddr + ((_pfn) * PAGE_SIZE)))
+static dom_meminfo_t *setup_guestos(int dom, int kernel_fd, int initrd_fd,
+    unsigned long virt_load_addr, size_t ksize, dom_mem_t *dom_mem)
+{
+    dom_meminfo_t *meminfo;
+    unsigned long *page_array;
+    page_update_request_t *pgt_updates;
+    dom_mem_t mem_map;
+    dom_meminfo_t *ret = NULL;
+    int alloc_index, num_pt_pages;
+    unsigned long l2tab;
+    unsigned long l1tab = 0;
+    unsigned long num_pgt_updates = 0;
+    unsigned long count, pt_start;
+    dom0_op_t pgupdate_req;
+    char cmd_path[MAX_PATH];
+    int cmd_fd;
+
+    meminfo     = (dom_meminfo_t *)malloc(sizeof(dom_meminfo_t));
+    page_array  = malloc(dom_mem->tot_pages * 4);
+    pgt_updates = (page_update_request_t *)dom_mem->vaddr;
+    alloc_index = dom_mem->tot_pages - 1;
+
+    memset(meminfo, 0, sizeof(meminfo));
+
+    memcpy(page_array, (void *)dom_mem->vaddr, dom_mem->tot_pages * 4);
+
+    /* Count bottom-level PTs, rounding up. Include one PTE for shared info. */
+    num_pt_pages = 
+        (l1_table_offset(virt_load_addr) + dom_mem->tot_pages + 1024) / 1024;
+
+    /* We must also count the page directory. */
+    num_pt_pages++;
+
+    /* Index of first PT page. */
+    pt_start = dom_mem->tot_pages - num_pt_pages;
+
+    /* first allocate page for page dir. allocation goes backwards from the
+     * end of the allocated physical address space.
+     */
+    l2tab = *(page_array + alloc_index) << PAGE_SHIFT; 
+    memset(PAGE_TO_VADDR(alloc_index), 0, PAGE_SIZE);
+    alloc_index--;
+    meminfo->l2_pgt_addr = l2tab;
+    meminfo->virt_shinfo_addr = virt_load_addr + nr_2_page(dom_mem->tot_pages);
+
+    /* pin down l2tab addr as page dir page - causes hypervisor to provide
+     * correct protection for the page
+     */ 
+    pgt_updates->ptr = l2tab | PGREQ_EXTENDED_COMMAND;
+    pgt_updates->val = PGEXT_PIN_L2_TABLE;
+    pgt_updates++;
+    num_pgt_updates++;
+
+    /*
+     * Initialise the page tables. The final iteration is for the shared_info
+     * PTE -- we break out before filling in the entry, as that is done by
+     * Xen during final setup.
+     */
+    l2tab += l2_table_offset(virt_load_addr) * sizeof(l2_pgentry_t);
+    for ( count = 0; count < (dom_mem->tot_pages + 1); count++ )
+    {    
+        if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) ) 
+        {
+            l1tab = *(page_array + alloc_index) << PAGE_SHIFT;
+            memset(PAGE_TO_VADDR(alloc_index), 0, PAGE_SIZE);
+            alloc_index--;
+                       
+            l1tab += l1_table_offset(virt_load_addr + nr_2_page(count)) 
+                * sizeof(l1_pgentry_t);
+
+            /* make apropriate entry in the page directory */
+            pgt_updates->ptr = l2tab;
+            pgt_updates->val = l1tab | L2_PROT;
+            pgt_updates++;
+            num_pgt_updates++;
+            l2tab += sizeof(l2_pgentry_t);
+        }
+
+        /* The last PTE we consider is filled in later by Xen. */
+        if ( count == dom_mem->tot_pages ) break;
+               
+        if ( count < pt_start )
+        {
+            pgt_updates->ptr = l1tab;
+            pgt_updates->val = (*(page_array + count) << PAGE_SHIFT) | L1_PROT;
+            pgt_updates++;
+            num_pgt_updates++;
+            l1tab += sizeof(l1_pgentry_t);
+        }
+        else
+        {
+            pgt_updates->ptr = l1tab;
+            pgt_updates->val = 
+               ((*(page_array + count) << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
+            pgt_updates++;
+            num_pgt_updates++;
+            l1tab += sizeof(l1_pgentry_t);
+        }
+
+        pgt_updates->ptr = 
+           (*(page_array + count) << PAGE_SHIFT) | PGREQ_MPT_UPDATE;
+        pgt_updates->val = count;
+        pgt_updates++;
+        num_pgt_updates++;
+    }
+
+    meminfo->virt_startinfo_addr = virt_load_addr + nr_2_page(alloc_index - 1);
+    meminfo->domain = dom;
+
+    /*
+     * Send the page update requests down to the hypervisor.
+     * NB. We must do this before loading the guest OS image!
+     */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    if ( (cmd_fd = open(cmd_path, O_WRONLY)) < 0 ) goto out;
+    pgupdate_req.cmd = DO_PGUPDATES;
+    pgupdate_req.u.pgupdate.pgt_update_arr  = (unsigned long)dom_mem->vaddr;
+    pgupdate_req.u.pgupdate.num_pgt_updates = num_pgt_updates;
+    write(cmd_fd, &pgupdate_req, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    /* Load the guest OS image. */
+    if( read(kernel_fd, (char *)dom_mem->vaddr, ksize) != ksize )
+    {
+        dberr("Error reading kernel image, could not"
+              " read the whole image. Terminating.\n");
+        goto out;
+    }
+
+    if( initrd_fd )
+      {
+       struct stat stat;
+       unsigned long isize;
+
+       if(fstat(initrd_fd, &stat) < 0){
+         perror(PERR_STRING);
+         close(initrd_fd);
+         goto out;
+       }
+       isize = stat.st_size;
+
+       if( read(initrd_fd, ((char *)dom_mem->vaddr)+ksize, isize) != isize )
+         {
+           dberr("Error reading initrd image, could not"
+                 " read the whole image. Terminating.\n");
+           goto out;
+         }
+
+       meminfo->virt_mod_addr = virt_load_addr + ksize;
+       meminfo->virt_mod_len  = isize;
+
+      }
+
+
+    ret = meminfo;
+out:
+
+    return ret;
+}
+
+static int launch_domain(dom_meminfo_t  * meminfo)
+{
+    char cmd_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        perror(PERR_STRING);
+        return -1;
+    }
+
+    dop.cmd = DOM0_BUILDDOMAIN;
+    memcpy(&dop.u.meminfo, meminfo, sizeof(dom_meminfo_t));
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    return 0;
+}
+
+static int get_domain_info (int domain_id,
+                            int *pg_head,
+                            int *tot_pages)
+{
+  FILE *f; 
+  char domains_path[MAX_PATH];
+  char domains_line[256];
+  int rc = -1;
+  int read_id;
+
+  sprintf (domains_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_DOMAINS
+);
+
+  f = fopen (domains_path, "r");
+  if (f == NULL) goto out;
+
+  read_id = -1;
+  while (fgets (domains_line, 256, f) != 0)
+    { 
+      int trans;
+      trans = sscanf (domains_line, "%d %*d %*d %*d %*d %*d %x %d %*s", &read_id
+, pg_head, tot_pages);
+      if (trans == 3) {
+        if (read_id == domain_id) {
+          rc = 0;
+          break;
+        }
+      }
+    }
+
+  if (read_id == -1) {
+    errno = ESRCH;
+  }
+
+  fclose (f);
+
+ out:
+  return rc;
+}
+
+
+int main(int argc, char **argv)
+{
+
+    dom_mem_t dom_os_image;
+    dom_mem_t dom_pgt; 
+    dom_meminfo_t * meminfo;
+    size_t ksize;
+    unsigned long load_addr;
+    char status[1024];
+    int kernel_fd, initrd_fd = 0;
+    int count;
+    int cmd_len;
+    int rc = -1;
+    int args_start = 4;
+    char initrd_name[1024];
+    int domain_id;
+    int pg_head;
+    int tot_pages;
+
+    unsigned long addr;
+
+    /**** this argument parsing code is really _gross_. rewrite me! ****/
+
+    if(argc < 4) {
+        dberr("Usage: dom_builder <domain_id> <image> <num_vifs> "
+             "[<initrd=initrd_name>] <boot_params>\n");
+        return -1;
+    }
+
+    /* Look up information about the domain */
+    domain_id = atol(argv[1]);
+    if (get_domain_info (domain_id, &pg_head, &tot_pages) != 0) {
+      perror ("Could not find domain information");
+      rc = -1;
+      goto out;
+    }
+            
+    kernel_fd = do_kernel_chcks(argv[2], tot_pages << (PAGE_SHIFT - 10), &load_addr, &ksize);
+    if(kernel_fd < 0)
+       return -1;
+    
+
+    /* map domain's memory */
+    if(map_dom_mem(pg_head, tot_pages,
+                  domain_id, &dom_os_image))
+        goto out;
+
+    if( strncmp("initrd=", argv[args_start], 7) == 0 )
+      {
+       strncpy( initrd_name, argv[args_start]+7, sizeof(initrd_name) );
+       initrd_name[sizeof(initrd_name)-1] = 0;
+       printf("initrd present, name = %s\n", initrd_name );
+       args_start++;
+
+       initrd_fd = open(initrd_name, O_RDONLY);
+       if(initrd_fd < 0){
+         perror(PERR_STRING);
+         goto out;
+       }
+      }
+
+    /* the following code does the actual domain building */
+    meminfo = setup_guestos(domain_id, kernel_fd, initrd_fd, load_addr, 
+                           ksize, &dom_os_image); 
+    
+    /* and unmap the new domain's memory image since we no longer need it */
+    dom_mem_cleanup(&dom_os_image);
+
+    if(!meminfo) { 
+       printf("Domain Builder: debug: meminfo NULL\n");
+        goto out;
+    }
+
+    meminfo->virt_load_addr = load_addr;
+    meminfo->num_vifs = atoi(argv[3]);
+    meminfo->cmd_line[0] = '\0';
+    cmd_len = 0;
+    for(count = args_start; count < argc; count++){
+        if(cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1){
+            dberr("Size of image boot params too big!\n");
+            break;
+        }
+        strcat(meminfo->cmd_line, argv[count]);
+        strcat(meminfo->cmd_line, " ");
+        cmd_len += strlen(argv[count] + 1);
+    }
+
+    /*    sprintf(status, 
+           "About to launch new domain %d with folowing parameters:\n"
+           " * page table base: %lx \n * load address: %lx \n"
+           " * shared info address: %lx \n * start info address: %lx \n"
+           " * number of vifs: %d \n * cmd line: %s \n", meminfo->domain, 
+           meminfo->l2_pgt_addr, meminfo->virt_load_addr, 
+           meminfo->virt_shinfo_addr, meminfo->virt_startinfo_addr, 
+           meminfo->num_vifs, meminfo->cmd_line);
+           dbstatus(status);*/
+    
+    /* and launch the domain */
+    rc = launch_domain(meminfo); 
+    
+out:
+    return rc;
+}
diff --git a/tools/internal/xi_create.c b/tools/internal/xi_create.c
new file mode 100644 (file)
index 0000000..5162e27
--- /dev/null
@@ -0,0 +1,98 @@
+/* 
+ * XenoDomainBuilder, copyright (c) Boris Dragovic, bd240@cl.cam.ac.uk
+ * This code is released under terms and conditions of GNU GPL :).
+ * Usage: <executable> <mem_kb> <os image> <num_vifs> 
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "hypervisor_defs.h"
+#include "dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+/***********************************************************************/
+
+static char *argv0 = "internal_domain_create";
+
+static void ERROR (char *message)
+{
+  fprintf (stderr, "%s: %s\n", argv0, message);
+  exit (-1);
+}
+
+static void PERROR (char *message)
+{
+  fprintf (stderr, "%s: %s (%s)\n", argv0, message, sys_errlist[errno]);
+  exit (-1);
+}
+
+/***********************************************************************/
+
+static dom0_newdomain_t * create_new_domain(long req_mem, char *name)
+{
+    dom0_newdomain_t * dom_data;
+    char cmd_path[MAX_PATH];
+    char dom_id_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+    int id_fd;
+
+    /* open the /proc command interface */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        PERROR ("Could not open PROC_CMD interface");
+        return 0;
+    }
+
+    dop.cmd = DOM0_CREATEDOMAIN;
+    dop.u.newdomain.memory_kb = req_mem;
+    strncpy (dop.u.newdomain.name, name, MAX_DOMAIN_NAME - 1);
+    dop.u.newdomain.name[MAX_DOMAIN_NAME - 1] = 0;
+
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    sprintf(dom_id_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", 
+        PROC_DOM_DATA);
+    while((id_fd = open(dom_id_path, O_RDONLY)) < 0) continue;
+    dom_data = (dom0_newdomain_t *)malloc(sizeof(dom0_newdomain_t));
+    read(id_fd, dom_data, sizeof(dom0_newdomain_t));
+    close(id_fd);
+    
+    return dom_data;
+}    
+
+/***********************************************************************/
+
+int main(int argc, char **argv)
+{
+  dom0_newdomain_t * dom_data;
+
+  if (argv[0] != NULL) 
+    {
+      argv0 = argv[0];
+    }
+
+  if(argc != 3) 
+    {
+      fprintf (stderr, "Usage: %s <kbytes-mem> <domain-name>\n", argv0);
+      return -1;
+    }
+
+  if(!(dom_data = create_new_domain(atol(argv[1]), argv[2]))) 
+    {
+      return -1;
+    }
+
+  fprintf (stdout, "%d\n", dom_data -> domain);
+  return 0;
+}
diff --git a/tools/internal/xi_destroy.c b/tools/internal/xi_destroy.c
new file mode 100644 (file)
index 0000000..b262609
--- /dev/null
@@ -0,0 +1,81 @@
+/* 
+ * A very(!) simple program to kill a domain. (c) Boris Dragovic
+ * Usage: <executable> <mem_kb> <os image> <num_vifs> 
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "dom0_ops.h"
+#include "dom0_defs.h"
+
+/***********************************************************************/
+
+static char *argv0 = "internal_domain_stop";
+
+static void ERROR (char *message)
+{
+  fprintf (stderr, "%s: %s\n", argv0, message);
+  exit (-1);
+}
+
+static void PERROR (char *message)
+{
+  fprintf (stderr, "%s: %s (%s)\n", argv0, message, sys_errlist[errno]);
+  exit (-1);
+}
+
+/***********************************************************************/
+
+static int do_kill_domain(int dom_id, int force)
+{
+    char cmd_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+
+    dop.cmd = DOM0_DESTROYDOMAIN;
+    dop.u.killdomain.domain = dom_id;
+    dop.u.killdomain.force  = force;
+
+    /* open the /proc command interface */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        PERROR ("Count not open PROC_CMD interface");
+    }
+
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    return 0;
+}
+
+int main(int argc, char **argv)
+{
+  int ret;
+
+  if (argv[0] != NULL) 
+    {
+      argv0 = argv[0];
+    }
+
+  if ( (argc < 2) || (argc > 3) )
+    {
+    usage:
+        fprintf(stderr, "Usage: %s [-f] <domain_id>\n", argv0);
+        fprintf(stderr, " -f: Forces immediate destruction of specified domain\n");
+        ret = -1;
+        goto out;
+    }
+
+    if ( (argc == 3) && strcmp("-f", argv[1]) ) goto usage;
+
+    ret = do_kill_domain(atoi(argv[argc-1]), argc == 3);
+
+out:
+    return ret;
+}
diff --git a/tools/internal/xi_start.c b/tools/internal/xi_start.c
new file mode 100644 (file)
index 0000000..7c03180
--- /dev/null
@@ -0,0 +1,80 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "hypervisor_defs.h"
+#include "dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+/***********************************************************************/
+
+static char *argv0 = "internal_domain_start";
+
+static void ERROR (char *message)
+{
+  fprintf (stderr, "%s: %s\n", argv0, message);
+  exit (-1);
+}
+
+static void PERROR (char *message)
+{
+  fprintf (stderr, "%s: %s (%s)\n", argv0, message, sys_errlist[errno]);
+  exit (-1);
+}
+
+/***********************************************************************/
+
+static int start_domain(int id)
+{
+    dom0_newdomain_t * dom_data;
+    char cmd_path[MAX_PATH];
+    char dom_id_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+    int id_fd;
+
+    /* Set up the DOM0_STARTDOMAIN command */
+    dop.cmd = DOM0_STARTDOMAIN;
+    dop.u.meminfo.domain = id;
+
+    /* open the /proc command interface */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        PERROR ("Count not open PROC_CMD interface");
+    }
+
+    /* Issue the command */
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    return 0;
+}    
+
+/***********************************************************************/
+
+int main(int argc, char **argv)
+{
+  int rc;
+
+  if (argv[0] != NULL) 
+    {
+      argv0 = argv[0];
+    }
+
+  if(argc != 2) 
+    {
+      fprintf (stderr, "Usage: %s <domain-id>\n", argv0);
+      return -1;
+    }
+
+  rc = start_domain(atol(argv[1]));
+
+  return rc;
+}
diff --git a/tools/internal/xi_stop.c b/tools/internal/xi_stop.c
new file mode 100644 (file)
index 0000000..cbed24d
--- /dev/null
@@ -0,0 +1,80 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "hypervisor_defs.h"
+#include "dom0_ops.h"
+#include "dom0_defs.h"
+#include "mem_defs.h"
+
+/***********************************************************************/
+
+static char *argv0 = "internal_domain_stop";
+
+static void ERROR (char *message)
+{
+  fprintf (stderr, "%s: %s\n", argv0, message);
+  exit (-1);
+}
+
+static void PERROR (char *message)
+{
+  fprintf (stderr, "%s: %s (%s)\n", argv0, message, sys_errlist[errno]);
+  exit (-1);
+}
+
+/***********************************************************************/
+
+static int stop_domain(int id)
+{
+    dom0_newdomain_t * dom_data;
+    char cmd_path[MAX_PATH];
+    char dom_id_path[MAX_PATH];
+    dom0_op_t dop;
+    int cmd_fd;
+    int id_fd;
+
+    /* Set up the DOM0_STOPDOMAIN command */
+    dop.cmd = DOM0_STOPDOMAIN;
+    dop.u.meminfo.domain = id;
+
+    /* open the /proc command interface */
+    sprintf(cmd_path, "%s%s%s%s", "/proc/", PROC_XENO_ROOT, "/", PROC_CMD);
+    cmd_fd = open(cmd_path, O_WRONLY);
+    if(cmd_fd < 0){
+        PERROR ("Count not open PROC_CMD interface");
+    }
+
+    /* Issue the command */
+    write(cmd_fd, &dop, sizeof(dom0_op_t));
+    close(cmd_fd);
+
+    return 0;
+}    
+
+/***********************************************************************/
+
+int main(int argc, char **argv)
+{
+  int rc;
+
+  if (argv[0] != NULL) 
+    {
+      argv0 = argv[0];
+    }
+
+  if(argc != 2) 
+    {
+      fprintf (stderr, "Usage: %s <domain-id>\n", argv0);
+      return -1;
+    }
+
+  rc = stop_domain(atol(argv[1]));
+
+  return rc;
+}
diff --git a/tools/internal/xi_vifinit b/tools/internal/xi_vifinit
new file mode 100755 (executable)
index 0000000..feac666
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# vifinit 
+#
+# This is a silly little script to dump a couple of simple rules down to 
+# the hypervisor to assign a full static IP to a given virtual interface.
+# 
+# Usage is:
+#
+#   vifinit [vif dom] [vif idx] [dotted decimal ip address]
+#
+if [ $# -ne 3 ] ; 
+then
+        echo "usage: $0 <domain_id> <vid_ifx> <dotted_decimal_ip_address>"
+        exit
+fi
+
+#outbound rule:
+echo "ADD ACCEPT srcaddr=$3 srcaddrmask=255.255.255.255 srcdom=$1 srcidx=$2 dst=PHYS proto=any" > /proc/vfr
+
+#inbound rule:
+echo "ADD ACCEPT dstaddr=$3 dstaddrmask=255.255.255.255 src=ANY dstdom=$1 dstidx=$2 proto=any" > /proc/vfr
+
+#----] done.
+
index 3ac6e72c0f3b78dbc6064572bbb6a5fa835ec8c8..fb8d44429e249fbf809935b0a4b816374bf0cd8a 100644 (file)
@@ -62,11 +62,19 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     switch ( op.cmd )
     {
 
-    case DOM0_STARTDOM:
+    case DOM0_BUILDDOMAIN:
     {
         struct task_struct * p = find_domain_by_id(op.u.meminfo.domain);
         if ( (ret = final_setup_guestos(p, &op.u.meminfo)) != 0 )
             break;
+        ret = p->domain;
+        free_task_struct(p);
+    }
+    break;
+
+    case DOM0_STARTDOMAIN:
+    {
+        struct task_struct * p = find_domain_by_id(op.u.meminfo.domain);
         wake_up(p);
         reschedule(p);
         ret = p->domain;
@@ -74,7 +82,13 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     }
     break;
 
-    case DOM0_NEWDOMAIN:
+    case DOM0_STOPDOMAIN:
+    {
+      ret = stop_other_domain (op.u.meminfo.domain);
+    }
+    break;
+
+    case DOM0_CREATEDOMAIN:
     {
         struct task_struct *p;
         static unsigned int pro = 0;
@@ -89,6 +103,11 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
         if ( p == NULL ) 
             break;
 
+       if (op.u.newdomain.name[0]) {
+         strncpy (p -> name, op.u.newdomain.name, MAX_DOMAIN_NAME);
+         p -> name[MAX_DOMAIN_NAME - 1] = 0;
+       }
+
         ret = alloc_new_dom_mem(p, op.u.newdomain.memory_kb);
         if ( ret != 0 ) 
         {
@@ -108,7 +127,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     }
     break;
 
-    case DOM0_KILLDOMAIN:
+    case DOM0_DESTROYDOMAIN:
     {
         unsigned int dom = op.u.killdomain.domain;
         int force = op.u.killdomain.force;
@@ -168,6 +187,38 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     }
     break;
 
+    case DOM0_GETDOMAININFO:
+    { 
+      struct task_struct *p;
+      u_long flags;
+
+      p = idle0_task.next_task;
+      read_lock_irqsave (&tasklist_lock, flags);
+      do {
+        if ((!is_idle_task (p)) && (p -> domain >= op.u.getdominfo.domain)) {
+          break;
+        }
+      } while ((p = p -> next_task) != &idle0_task);
+
+      if (p == &idle0_task) {
+        ret = -ESRCH;
+      } else {
+        op.u.getdominfo.domain = p -> domain;
+        strcpy (op.u.getdominfo.name, p -> name);
+        op.u.getdominfo.processor = p -> processor;
+        op.u.getdominfo.has_cpu = p -> has_cpu;
+        op.u.getdominfo.state = p -> state;
+        op.u.getdominfo.hyp_events = p -> hyp_events;
+        op.u.getdominfo.mcu_advance = p -> mcu_advance;
+        op.u.getdominfo.pg_head = list_entry(p->pg_head.next,
+                                             struct pfn_info, list) - frame_table;
+        op.u.getdominfo.tot_pages = p -> tot_pages;
+      }
+      read_unlock_irqrestore (&tasklist_lock, flags);
+      copy_to_user(u_dom0_op, &op, sizeof(op));
+      break;
+    }
+
     default:
         ret = -ENOSYS;
 
index f54e7c9d67d40bc1ebaa388481c5f4e932a2eadf..35154baf37cbc73e5598f9700c16be75fe5ba511 100644 (file)
@@ -175,6 +175,29 @@ long kill_other_domain(unsigned int dom, int force)
     return 0;
 }
 
+void stop_domain(void)
+{
+  current -> state = TASK_SUSPENDED;
+  clear_bit(_HYP_EVENT_STOP, &(current->hyp_events));
+  schedule ();
+}
+
+long stop_other_domain(unsigned int dom)
+{
+  unsigned long cpu_mask;
+  struct task_struct *p;
+
+  p = find_domain_by_id (dom);
+  if ( p == NULL) return -ESRCH;
+
+  if ( p -> state != TASK_SUSPENDED )
+    {
+      cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP);
+      hyp_event_notify(cpu_mask);
+    }
+
+  return 0;
+}
 
 unsigned int alloc_new_dom_mem(struct task_struct *p, unsigned int kbytes)
 {
index 5749d27d4a4693f209fb30a5b8964a977e1c6ce7..6536bf1ba51439c1e2f6f0a887ab16b31ab2e028 100644 (file)
@@ -349,6 +349,7 @@ asmlinkage void schedule(void)
     case TASK_UNINTERRUPTIBLE:
     case TASK_WAIT:
     case TASK_DYING:
+    case TASK_SUSPENDED:
     default:
         /* done if not running. Else, continue */
         goto deschedule_done;
index ea3f829d731e5081899e51cde07a5f600ee53a38..8737e192aa7d8e73dfded2dd4d9fd066246f4ddd 100644 (file)
 #ifndef __DOM0_OPS_H__
 #define __DOM0_OPS_H__
 
-#define DOM0_NEWDOMAIN   0
-#define DOM0_KILLDOMAIN  1
-#define DOM0_GETMEMLIST  2
-#define DOM0_STARTDOM    4
-#define DOM0_BVTCTL      6
-#define DOM0_ADJUSTDOM   7
+#define DOM0_GETMEMLIST     2
+#define DOM0_BVTCTL         6
+#define DOM0_ADJUSTDOM      7
+#define DOM0_CREATEDOMAIN   8
+#define DOM0_DESTROYDOMAIN  9
+#define DOM0_STARTDOMAIN   10
+#define DOM0_STOPDOMAIN    11
+#define DOM0_GETDOMAININFO 12
+#define DOM0_BUILDDOMAIN   13
 
 #define MAX_CMD_LEN    256
+#define MAX_DOMAIN_NAME 16
 
 typedef struct dom0_newdomain_st 
 {
@@ -27,6 +31,7 @@ typedef struct dom0_newdomain_st
     unsigned int memory_kb; 
     unsigned int num_vifs;  // temporary
     unsigned long pg_head;  // return parameter
+    char name[MAX_DOMAIN_NAME];
 } dom0_newdomain_t;
 
 typedef struct dom0_killdomain_st
@@ -69,6 +74,20 @@ typedef struct dom0_adjustdom_st
        unsigned long warpu;    /* unwarp time requirement */
 } dom0_adjustdom_t;
 
+typedef struct dom0_getdominfo_st
+{
+  unsigned int domain;          /* All returns except domain */
+  char name[MAX_DOMAIN_NAME];
+  int processor;
+  int has_cpu;
+  int state;
+  int hyp_events;
+  unsigned long mcu_advance;
+  unsigned long pg_head;
+  unsigned int tot_pages;
+} dom0_getdominfo_t;
+
+
 typedef struct dom0_op_st
 {
     unsigned long cmd;
@@ -80,7 +99,8 @@ typedef struct dom0_op_st
                dom0_bvtctl_t bvtctl;
                dom0_adjustdom_t adjustdom;
         dom_meminfo_t meminfo;
-    }
+        dom0_getdominfo_t getdominfo;
+   }
     u;
 } dom0_op_t;
 
index d29c7f9e498f6ea08207b9b6723d478fe78e1bfe..fe4c49736e8c2ca1691c9db67d50ccfdc17c856e 100644 (file)
@@ -16,6 +16,8 @@
 #include <xeno/time.h>
 #include <xeno/ac_timer.h>
 
+#define MAX_DOMAIN_NAME 16
+
 extern unsigned long volatile jiffies;
 extern rwlock_t tasklist_lock;
 
@@ -51,6 +53,7 @@ extern struct mm_struct init_mm;
 
 #define _HYP_EVENT_NEED_RESCHED 0
 #define _HYP_EVENT_DIE          1
+#define _HYP_EVENT_STOP         2
 
 #define PF_DONEFPUINIT  0x1  /* Has the FPU been initialised for this task? */
 #define PF_USEDFPU      0x2  /* Has this task used the FPU since last save? */
@@ -141,6 +144,8 @@ struct task_struct
                                        0-0xFFFFFFFF for kernel-thread
                                      */
 
+    char name[MAX_DOMAIN_NAME];
+
     /*
      * active_mm stays for now. It's entangled in the tricky TLB flushing
      * stuff which I haven't addressed yet. It stays until I'm man enough
@@ -223,6 +228,8 @@ extern void __kill_domain(struct task_struct *p);
 extern void kill_domain(void);
 extern void kill_domain_with_errmsg(const char *err);
 extern long kill_other_domain(unsigned int dom, int force);
+extern void stop_domain(void);
+extern long stop_other_domain(unsigned int dom);
 
 /* arch/process.c */
 void new_thread(struct task_struct *p,
index d3e4752eb388efb511d25d5b9b2f336658d283e7..4f03fda0e23f0b5909c51115cb311ab3a119e9ad 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/iobuf.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/seq_file.h>
 
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
@@ -31,6 +32,9 @@
 
 #include "dom0_ops.h"
 
+#define TRUE  1
+#define FALSE 0
+
 /* Private proc-file data structures. */
 typedef struct proc_data {
     unsigned int domain;
@@ -45,6 +49,7 @@ typedef struct proc_mem_data {
 #define XENO_BASE       "xeno"
 #define DOM0_CMD_INTF   "dom0_cmd"
 #define DOM0_NEWDOM     "new_dom_data"
+#define DOM_LIST_INTF   "domains"
 
 #define MAX_LEN         16
 #define DOM_DIR         "dom"
@@ -56,6 +61,7 @@ typedef struct proc_mem_data {
 struct proc_dir_entry *xeno_base;
 static struct proc_dir_entry *dom0_cmd_intf;
 static struct proc_dir_entry *proc_ft;
+static struct proc_dir_entry *dom_list_intf;
 
 unsigned long direct_mmap(unsigned long, unsigned long, pgprot_t, int, int);
 int direct_unmap(unsigned long, unsigned long);
@@ -266,7 +272,7 @@ static int cmd_write_proc(struct file *file, const char *buffer,
         ret = HYPERVISOR_dom0_op(&op);
 
         /* if new domain created, create proc entries */
-        if(op.cmd == DOM0_NEWDOMAIN){
+        if(op.cmd == DOM0_CREATEDOMAIN) {
             create_proc_dom_entries(ret);
 
             params = (dom0_newdomain_t *)kmalloc(sizeof(dom0_newdomain_t),
@@ -295,6 +301,94 @@ out:
     
 }
 
+/***********************************************************************
+ *
+ * Implementation of /proc/xeno/domains
+ */
+
+static dom0_op_t proc_domains_op;
+static int proc_domains_finished;
+static rwlock_t proc_xeno_domains_lock = RW_LOCK_UNLOCKED;
+
+static void *xeno_domains_next(struct seq_file *s, void *v, loff_t *pos)
+{
+  int ret;
+
+  if (pos != NULL) { ++ (*pos); }
+  if (!proc_domains_finished) {
+    proc_domains_op.u.getdominfo.domain ++;
+    ret = HYPERVISOR_dom0_op(&proc_domains_op);
+    if (ret < 0) proc_domains_finished = TRUE;
+  }
+  
+  return (proc_domains_finished) ? NULL : &proc_domains_op;
+}
+
+static void *xeno_domains_start(struct seq_file *s, loff_t *ppos)
+{ 
+  loff_t pos = *ppos;
+  
+  write_lock (&proc_xeno_domains_lock);
+  proc_domains_op.cmd = DOM0_GETDOMAININFO;
+  proc_domains_op.u.getdominfo.domain = 0;
+  (void)HYPERVISOR_dom0_op(&proc_domains_op);
+  proc_domains_finished = FALSE;
+  
+  while (pos > 0) {
+    pos --;
+    xeno_domains_next (s, NULL, NULL);
+  }
+  
+  return (proc_domains_finished) ? NULL : &proc_domains_op;
+}
+
+static void xeno_domains_stop(struct seq_file *s, void *v)
+{ 
+  write_unlock (&proc_xeno_domains_lock);
+}
+
+static int xeno_domains_show(struct seq_file *s, void *v)
+{ 
+  dom0_op_t *di = v;
+  
+  seq_printf (s, 
+              "%8d %2d %1d %2d %8d %8ld %p %8d %s\n",
+              di -> u.getdominfo.domain, 
+              di -> u.getdominfo.processor,
+              di -> u.getdominfo.has_cpu,
+              di -> u.getdominfo.state,
+              di -> u.getdominfo.hyp_events,
+              di -> u.getdominfo.mcu_advance,
+              di -> u.getdominfo.pg_head,
+              di -> u.getdominfo.tot_pages,
+              di -> u.getdominfo.name);
+
+  return 0;
+}
+
+struct seq_operations xeno_domains_op = {
+        .start          = xeno_domains_start,
+        .next           = xeno_domains_next,
+        .stop           = xeno_domains_stop,
+        .show           = xeno_domains_show,
+};
+
+static int xeno_domains_open(struct inode *inode, struct file *file)
+{
+        return seq_open(file, &xeno_domains_op);
+}
+
+static struct file_operations proc_xeno_domains_operations = {
+        open:           xeno_domains_open,
+        read:           seq_read,
+        llseek:         seq_lseek,
+        release:        seq_release,
+};
+
+/***********************************************************************/
+
+
+
 static int __init init_module(void)
 {
     /* xeno proc root setup */
@@ -311,6 +405,15 @@ static int __init init_module(void)
         dom0_cmd_intf->write_proc = cmd_write_proc;
     }
 
+    /* domain list interface */
+    dom_list_intf = create_proc_entry (DOM_LIST_INTF, 0400, xeno_base);
+    if ( dom_list_intf != NULL )
+      {
+        dom_list_intf -> owner = THIS_MODULE;
+        dom_list_intf -> nlink = 1;
+        dom_list_intf -> proc_fops = &proc_xeno_domains_operations;
+      }
+
     /* set up /proc entries for dom 0 */
     create_proc_dom_entries(0);
 
index 74c9b24de74485cdee5dba707566732fe6e414d7..1a5b63dad26e0e26bcbb8ad3fc6b73613602af36 100644 (file)
@@ -9,17 +9,21 @@
  * MUST BE KEPT IN SYNC WITH tools/domain_builder/dom0_ops.h
  */
 
-#define DOM0_NEWDOMAIN   0
-#define DOM0_KILLDOMAIN  1
-#define DOM0_GETMEMLIST  2
-#define DOM0_STARTDOM    4
-#define DOM0_BVTCTL      6
-#define DOM0_ADJUSTDOM   7
-#define MAP_DOM_MEM      8 /* Not passed down to Xen */
-#define DO_PGUPDATES     9 /* Not passed down to Xen */
-#define MAX_CMD         10
+#define DOM0_GETMEMLIST     2
+#define DOM0_BVTCTL         6
+#define DOM0_ADJUSTDOM      7
+#define DOM0_CREATEDOMAIN   8
+#define DOM0_DESTROYDOMAIN  9
+#define DOM0_STARTDOMAIN   10
+#define DOM0_STOPDOMAIN    11
+#define DOM0_GETDOMAININFO 12
+#define DOM0_BUILDDOMAIN   13
+#define MAP_DOM_MEM        14 /* Not passed down to Xen */
+#define DO_PGUPDATES       15 /* Not passed down to Xen */
+#define MAX_CMD            16
 
 #define MAX_CMD_LEN     256
+#define MAX_DOMAIN_NAME 16
 
 typedef struct dom0_newdomain_st
 {
@@ -27,6 +31,7 @@ typedef struct dom0_newdomain_st
     unsigned int memory_kb;
     unsigned int num_vifs;  /* temporary */
     unsigned long pg_head;  /* return parameter */
+    char name[MAX_DOMAIN_NAME];
 } dom0_newdomain_t;
 
 typedef struct dom0_killdomain_st
@@ -86,6 +91,19 @@ typedef struct domain_launch
 } dom_meminfo_t;
 
 
+typedef struct dom0_getdominfo_st
+{
+  unsigned int domain;          /* All returns except domain */
+  char name[MAX_DOMAIN_NAME];
+  int processor;
+  int has_cpu;
+  int state;
+  int hyp_events;
+  unsigned long mcu_advance;
+  unsigned long pg_head;
+  unsigned int tot_pages;
+} dom0_getdominfo_t;
+
 
 typedef struct dom0_op_st
 {
@@ -100,7 +118,8 @@ typedef struct dom0_op_st
         dom_mem_t dommem;
         dom_pgupdate_t pgupdate;
         dom_meminfo_t meminfo;
-    }
+        dom0_getdominfo_t getdominfo;
+   }
     u;
 } dom0_op_t;